#ifndef MCBL_BOOT_H_
#define MCBL_BOOT_H_


#define BOOT_BLOCK_SIZE_MAX     0x80
#define NONE                    0
#define FLG                     1

#define IHEX_SZ_MAX     0x20
typedef struct {
    struct {
        uint32_t length;
        uint32_t to;
        } head;
    uint8_t  payload[IHEX_SZ_MAX];
} Btx;

typedef union {
    struct {
        struct {
            uint32_t entry;
             int32_t length;
            uint32_t to;
        } head;
        uint8_t  payload[IHEX_SZ_MAX];
    }   bt0;
    Btx btx;
} Btbl;


#define BOOT_MODE_PIN_SLEEP_EMIF25       0
#define BOOT_MODE_PIN_SRIO               1
#define BOOT_MODE_PIN_ETH_CORE_CLK       2
#define BOOT_MODE_PIN_ETH_PA_CLK         3
#define BOOT_MODE_PIN_PCIE               4
#define BOOT_MODE_PIN_I2C                5
#define BOOT_MODE_PIN_SPI                6
#define BOOT_MODE_PIN_VUSR               7

/* sub modes for sleep/emif25 */
#define BOOT_MODE_PIN_SLEEP_EMIF25_SUBMODE_SLEEP   0
#define BOOT_MODE_PIN_SLEEP_EMIF25_SUBMODE_EMIF25  1

#define BOOT_MODE_ETH               10
#define BOOT_MODE_RAPIDIO           20
#define BOOT_MODE_PCIE              30
#define BOOT_MODE_I2C               40
#define BOOT_MODE_I2C_PASSIVE       41
#define BOOT_MODE_I2C_MASTER_WRITE  42
#define BOOT_MODE_SPI               50
#define BOOT_MODE_VUSR              60
#define BOOT_MODE_EMIF16            70
#define BOOT_MODE_SLEEP             100



#define DFE_SMP_MASK        0x00000000//AMP
#define FCFG                "mcbl.conf"
#define DEF_BL_IMG          "mcbl.hex"
#define DEF_BASE_ING        "base.hex"
#define DEF_UING(CORE)      "core_"#CORE".hex"
#define BOOT_MAGIC(CORE)    (0x10000000 + PRIVATE_MEM_BASE + 0x01000000 * CORE + PRIVATE_MEM_SIZE - 4)


typedef struct {
    char     image[CORE_ENTRY_MAX + 1][32];//+1 for bootloader

    uint32_t bootloaderSz;
    uint32_t uimgTotalSz;

    uint32_t smpMask;
    uint32_t curingCoreApp;

    uint32_t curingBootloader;
    uint32_t runBootloader;
    uint32_t bootMode;
    uint32_t coreCnt;
} McblCfg;

typedef struct {
    char     UDATE[31];
    uint8_t  CORES;

    uint32_t SMPM;
    Btbl*    BTBLT[ALL_CORES];
} McblImgDesc;

#define CSL_MCBL_CORE_CNT_MASK      0xFF000000
#define CAL_MCBL_CORE_CNT_SHIFT     24
#define MCBL_CORE_CNT               ALL_CORES

#define CSL_MCBL_SMPM_MASK          0x000000FF
#define CSL_MCBL_SMPM_SHIFT         0
#define MCBL_SMPM_ALL               0x000000FF
#define MCBL_SMPM_ALL_AMP           0x00000000

#define MCBL_ENTRY_VAL_MASK         0xFFFFFFFC
#define MCBL_ENTRY_VAL_INVALID      0xFFFFFFFC

#define CSL_MCBL_ENTRY_VALID_MASK   0x00000001
#define CSL_MCBL_ENTRY_VALID_SHIFT  0
#define MCBL_ENTRY_VALID            1
#define MCBL_ENTRY_INVALID          0

#define MCBL_ALIGN                  0x20

static inline uint16_t swap16(uint16_t b16) {
    return (((b16 & 0x00FF) << 8) | (b16 >>8));
}
static inline uint32_t swap32(uint32_t b32) {
    return \
    ((((uint32_t)(b32) & 0xff000000) >> 24) | \
     (((uint32_t)(b32) & 0x00ff0000) >>  8) | \
     (((uint32_t)(b32) & 0x0000ff00) <<  8) | \
     (((uint32_t)(b32) & 0x000000ff) << 24));
}

#if _BIG_ENDIAN
#define h2nqb(l)     (l)
#define nqb2h(l)     (l)
#define h2ndb(s)     (s)
#define ndb2h(s)     (s)
#else
#define h2ndb(s)     swap16(s)
#define ndb2h(s)     swap16(s)
#define h2nqb(l)     swap32(l)
#define nqb2h(l)     swap32(l)
#endif


typedef void(*Write)(uint32_t ct, void* from, int32_t size);
typedef void(*Entry)(void);


extern void main(void);
extern void boot(void);
extern void errHang(void);
extern void _c_int00(void);
extern void setup(CorePac core);
extern void curing(McblCfg* cfg);

extern
void __section(".loader")
load(
    McblImgDesc* descriptor,
    CorePac      core
);
//extern int  flashErase(void* from, int size);
//extern int  flashWrite(void* to, void* from, int size);

#endif /* MCBL_BOOT_H_ */
